import * as monaco from 'monaco-editor';

type IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
type ILanguage = monaco.languages.IMonarchLanguage;

export const conf: IRichLanguageConfiguration = {
  autoClosingPairs: [
    { close: '}', open: '{' },
    { close: ']', open: '[' },
    { close: ')', open: '(' },
    { close: '"', open: '"' },
    { close: "'", open: "'" },
  ],
  brackets: [
    ['{', '}'],
    ['[', ']'],
    ['(', ')'],
  ],
  comments: {
    lineComment: '#',
  },
  surroundingPairs: [
    { close: '}', open: '{' },
    { close: ']', open: '[' },
    { close: ')', open: '(' },
    { close: '"', open: '"' },
    { close: "'", open: "'" },
  ],
};

export const language = <ILanguage>{
  defaultToken: '',
  // we include these common regular expressions
  escapes: /\\(?:["'\\abfnrtv]|x[\dA-Fa-f]{1,4}|u[\dA-Fa-f]{4}|U[\dA-Fa-f]{8})/,

  // The main tokenizer for our languages
  tokenizer: {
    boolean: [[/\b(true|false)\b/, 'constant.other.boolean.toml']],

    // array: [{ include: '@comments' }, { include: '@dataTypes' }],

    comments: [
      [
        /\s*((#).*)$/,
        {
          cases: {
            $1: 'comment.line.number-sign.toml',
            $2: 'punctuation.definition.comment.toml',
          },
        },
      ],
    ],

    date: [[/(\d{4}-\d{2}-\d{2})/, 'constant.other.date.toml']],

    // dataTypes: [
    //   // { include: '#inlinetable' },
    //   // { include: '#array' },

    //   { include: '@dateTimeWithTz' },
    //   { include: '@dateTime' },
    //   { include: '@date' },
    //   { include: '@float' },
    //   { include: '@integer' },
    //   { include: '@boolean' },
    // ],

    dateTime: [
      [
        /(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?)/,
        'constant.other.datatime.toml',
      ],
    ],

    dateTimeWithTz: [
      [
        /\b(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2}))\b/,
        'constant.other.datetime-with-timezone.toml',
      ],
    ],

    float: [
      [
        /(?<!\w)([+-]?(0|([1-9]((\d|_\d)+)?))(?:(?:\.(0|([1-9]((\d|_\d)+)?)))?e[+-]?[1-9]_?\d*|\.[\d_]*))(?!\w)/i,
        'constant.numeric.float.toml',
      ],
    ],

    integer: [
      [
        /(?<!\w)([+-]?(0|([1-9]((\d|_\d)+)?)))\b/,
        'constant.numeric.integer.toml',
      ],
    ],

    keys: [[/(^\w+)(\s*)(=)/, ['key', '', 'delimiter']]],

    root: [
      // sections
      // [/^\[[^\]]*\]/, 'metatag'],

      { include: '@comments' },
      { include: '@tables' },
      { include: '@keys' },
      // { include: '@dataTypes' },

      // whitespace
      { include: '@whitespace' },

      // { include: '@float' },
      // { include: '@integer' },

      // strings: recover on non-terminated strings
      // [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
      // [/'([^'\\]|\\.)*$/, 'string.invalid'], // non-teminated string
      // [/"/, 'string', '@string."'],
      // [/'/, 'string', "@string.'"],
      { include: '@dateTimeWithTz' },
      { include: '@dateTime' },
      { include: '@date' },
      { include: '@float' },
      { include: '@integer' },
      { include: '@boolean' },
      { include: '@string' },
    ],

    string: [
      [/["'\\]+/, 'string.quoted.single.literal.line.toml'],
      // [/[^\\"]+/, 'string.quoted.single.basic.line.toml'],
      [/@escapes/, 'constant.character.escape.toml'],
      [/\\./, 'invalid.illegal.escape.toml'],
      [
        /["']/,
        {
          cases: {
            '$#==$S2': {
              next: '@pop',
              token: 'string.quoted.triple.literal.block.toml',
            },
            '@default': 'string.quoted.triple.literal.block.toml',
          },
        },
      ],
      [/[^"'\\]+/, 'string'],
      [/@escapes/, 'string.escape'],
      [/\\./, 'string.escape.invalid'],
      [
        /["']/,
        {
          cases: {
            '$#==$S2': { next: '@pop', token: 'string' },
            '@default': 'string',
          },
        },
      ],
    ],

    // eslint-disable-next-line unicorn/better-regex
    tables: [[/^\[\\[^\]]*\]/, 'punctuation.definition.table.toml']],

    whitespace: [[/[\t\n\r ]+/, '']],
    // tables: [
    //   [
    //     /^\s*(\[)([^[\]]*)(\])/,
    //     {
    //       cases: {
    //         $1: 'punctuation.definition.table.toml',
    //         $2: [[/[^s.]+/, 'entity.other.attribute-name.table.toml']],
    //         $3: 'punctuation.definition.table.toml',
    //       },
    //     },
    //   ],
    //   [
    //     /^\s*(\[\[)([^[\]]*)(\]\])/,
    //     {
    //       cases: {
    //         $1: 'punctuation.definition.table.array.toml',
    //         $2: [[/[^s.]+/, 'entity.other.attribute-name.table.array.toml']],
    //         $3: 'punctuation.definition.table.array.toml',
    //       },
    //     },
    //   ],
    // ],
  },

  tokenPostfix: '.toml',
};
